package cate.game.fight.task;

import cate.common.table.d.GDFight;
import cate.game.GameBody;
import cate.game.fight.FightTaskContext;
import cate.game.framework.ThreadShare;
import cate.game.play.proce.play.PlayPO;
import cate.game.role.Role;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FightTask {

    private Logger logger = LoggerFactory.getLogger(FightTask.class);

    /** 战斗上下文 */
    public FightTaskContext context;

    /** 战斗的剧本 */
    public PlayPO play;

    /** master._idHex */
    private String roleUid;

    private GameBody game;

    /** 是否属于该master的 */
    public boolean belong(Role role, int funcId) {
        if (role == null) {
            return false;
        }
        if (context == null) {
            return false;
        }
        return context.funcId == funcId && StringUtils.equals(roleUid, role.getUid());
    }

    // ----------------------------------------
    /** 当前播放速度 */
    private double playSpeed = 1;

    private double getPlaySpeed() {
        Role master = game.role.getRoleFromActive(roleUid);
        if (master == null) {
            //
        } else {
            playSpeed = master.getSystem().playRate;
        }
        if (context.playSpeed != null) {
            playSpeed = context.playSpeed;
        }
        return playSpeed;
    }

    public FightTask(GameBody game, FightTaskContext context, PlayPO play, String roleUid) {
        this.game = game;
        this.context = context;
        this.play = play;
        this.roleUid = roleUid;
        getPlaySpeed();
    }

    /** 是否在看 */
    private boolean isWatching() {
        Role role = game.role.getRoleFromActive(roleUid);
        if (role != null && role.getStatus().isOnline()) {
            boolean watching = false;
            try {
                watching = role.getFight().action.getWatching(context.funcId);
            } catch (Exception e) {
                logger.error("FightTask:canAutoFinish时", e);
            }
            return watching;
        }
        return false;
    }

    /** 能否自动完成？ 如果是前段发起的请求完成，是调用isFinished() 这里要额外对是否观测进行判断，如果玩家在看这场战斗的话，那么不允许服务器主动完成，需要等前端发起请求 */
    public boolean canAutoFinish() {
        if (isWatching()) {
            return false;
        }
        return isFinished(false);
    }

    /**
     * 是否已完成
     *
     * @param manual 是否人工触发
     */
    public boolean isFinished(boolean manual) {
        long now = System.currentTimeMillis();
        long pastReal = now - play.startTime;
        pastReal *= this.playSpeed;
        long pastNeed = play.endTime - play.startTime;
//        if (pastNeed > 5 * 60000) {
//            logger.warn("该剧本超过5分钟, {}ms", pastNeed);
//        }
        if (manual) {
            if (pastNeed - pastReal < GDFight.FINISH_TIME_TOLERANCE) {
                return true;
            }
            return false;
        }
        return (pastNeed - pastReal < 0);
    }

    /** 无论如何也该结束 */
    public boolean isFinishedWhatever() {
        if (isWatching()) {
            return false;
        }
        return System.currentTimeMillis() >= this.play.endTime;
    }

    /** 任务是否失效 */
    public boolean invalid() {
        return settled;
    }

    /** 是否已结算 */
    private boolean settled = false;

    /**
     * 是否可处理，如果可以处理，就从tasks中移除，然后去指定handleResult了
     *
     * @param skip 强制要求跳过
     */
    public boolean allowHandle(Role role, boolean skip, boolean manual) {
        if (!isFinished(manual) && !skip) {
            role.getGame().notice.message(role, "战斗激烈，意犹未尽！");
            return false;
        }
        return true;
    }

    /** 处理战斗结果 包括（发放奖励，通知结算等） */
    public void handleResult(Role role) {
        if (this.settled) {
            return;
        }
        this.settled = true;
        if (role == null) {
            role = game.role.getRole(this.roleUid);
        }
        try {
            final Role _role = role;
            ThreadShare.instance().exe(role, () -> {
                context.handleResult(_role, play);
                //入口处做统一处理，就不用一个个功能添加了
            });
        } catch (Exception e) {
            logger.error("context处理结果时错误", e);
        }
    }

    /** 处理战斗结果 包括（发放奖励，通知结算等） */
    public void handleResultSelfThread(Role role) {
        if (this.settled) {
            return;
        }
        this.settled = true;
        if (role == null) {
            role = game.role.getRole(this.roleUid);
        }
        try {
            context.handleResult(role, play);
        } catch (Exception e) {
            logger.error("context处理结果时错误", e);
        }
    }
}
